import logging
import socket
import sys
from Crypto.Cipher import ARC4

import rsa
from rsa import PublicKey

sys.path.append('..')
from transfer.common import randomword, get_file_sha1, get_host_ip

PublicKey

LOG = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG)

LOCALHOST = get_host_ip()
PORT_WAITING = 5555
PORT_FILE = 6666
PORT_DIGEST = 7777

PUBLIC_KEY, PRIVATE_KEY = rsa.newkeys(1024)
PUBLIC_KEY_LEN = len(str(PUBLIC_KEY)) + 1
RC4_KEY_LEN = 128


class Sender(object):
    def __init__(self, port):

        self.s = socket.socket()
        self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.s.bind((LOCALHOST, port))
        self.receiver_public_key = None
        self.conn = None
        self.addr = None
        self.rc4_key = None
        self.s.listen(5)

    def accept(self):
        while True:
            self.conn, self.addr = self.s.accept()
            LOG.debug('Got connection from %s', str(self.addr))
            break

    def close(self):
        self.conn.close()

    def send(self, msg):
        self.conn.send(msg)

    def shake_hand(self):
        LOG.debug('shaking hand with %s', str(self.addr))
        self.send(str(PUBLIC_KEY))
        self.receiver_public_key = eval(self.conn.recv(PUBLIC_KEY_LEN))
        LOG.debug('receive public key: %s' % self.receiver_public_key)
        self.rc4_key = randomword(RC4_KEY_LEN / 2)
        self.send(rsa.encrypt(self.rc4_key, self.receiver_public_key))
        msg = self.conn.recv(1024)
        msg = rsa.decrypt(msg, PRIVATE_KEY)
        self.rc4_key += msg
        LOG.debug('rc4 key: %s' % self.rc4_key)

    def send_file(self, file_path):

        filename = file_path
        LOG.debug('opening file : %s' % file_path)
        f = open('%s' % filename, 'rb')
        l = f.read(1024)
        datalen = len(l)
        cipher = ARC4.new(self.rc4_key)
        while l:
            datalen += len(l)
            msg = cipher.encrypt(l)
            self.send(msg)
            l = f.read(1024)
        f.close()
        self.close()
        LOG.debug('successfully sent %d Byte of data' % datalen)

    def send_digest(self, file_path):
        self.accept()
        self.shake_hand()
        signature = str(rsa.sign(get_file_sha1('%s' % file_path), PRIVATE_KEY, 'SHA-1'))
        self.send(signature)
        LOG.debug(len(signature))
        self.close()


if __name__ == '__main__':
    server = Sender(PORT_FILE)
    server.accept()
    server.shake_hand()
    server.send_file('in.pdf')
    server1 = Sender(PORT_DIGEST)
    server1.send_digest('in.pdf')
